/*
* Change Logs:
* Date           Author       Notes
* 2020-10-15     chenbin      
* 2020-11-13     chenbin      
*/
#include "stdio.h"
#include "string.h"
#include "rtthread.h"
#include "rtdevice.h"
#include "board.h"

#define DBG_TAG "can1"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#define CAN1_DEVICE_NAME			"can1"

//static uint8_t temp_buff[256] = {0};

static 				rt_device_t			can1_dev;     /* CAN 设备句柄 */
static struct rt_semaphore		can1_rx_sem;     /* 用于接收消息的信号量 */

/* 接收数据回调函数 */
static rt_err_t can1_rx_call(rt_device_t dev, rt_size_t size)
{
    /* CAN 接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&can1_rx_sem);

    return RT_EOK;
}


void can1_send_0x123(void)
{
	struct rt_can_msg msg = {0};
	msg.id =  0x123;              /* ID 为 0x78 */
	msg.ide = RT_CAN_STDID;     /* 标准格式 */
	msg.rtr = RT_CAN_DTR;       /* 数据帧 */
	msg.len = 8;                /* 数据长度为 8 */
	/* 待发送的 8 字节数据 */
	msg.data[0] = 0x00;
	msg.data[1] = 0x11;
	msg.data[2] = 0x22;
	msg.data[3] = 0x33;
	msg.data[4] = 0x44;
	msg.data[5] = 0x55;
	msg.data[6] = 0x66;
	msg.data[7] = 0x77;
	/* 发送一帧 CAN 数据 */
	int rc = rt_device_write(can1_dev, 0, &msg, sizeof(msg));
	if(rc != RT_CAN_SND_RESULT_OK)
	{
	    rt_kprintf("can dev write data ,rc:%d\n",rc);
	}else {
	    rt_kprintf("can dev write data ,rc:%d ok\n",rc);
    }
}


static void can1_thread(void *param)
{
	int rc = 0;
//  struct can_configure can_config = CANDEFAULTCONFIG;
	
	can1_dev = rt_device_find(CAN1_DEVICE_NAME);
	if (!can1_dev)
	{
			rt_kprintf("find %s failed!\n", CAN1_DEVICE_NAME);
			return ;
	}
	
	rt_sem_init(&can1_rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
	
//	can_config.baud_rate = CAN500kBaud;
//	can_config.mode = RT_CAN_MODE_NORMAL;
//	rt_device_control(can1_dev, RT_DEVICE_CTRL_CONFIG, &(can_config));

    rt_device_control(can1_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN500kBaud);

    rt_device_control(can1_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_NORMAL);
    //rt_device_control(can1_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_LOOPBACK);
	
	/* 以中断接收及发送方式打开 CAN 设备 */
	rc = rt_device_open(can1_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
	RT_ASSERT(rc == RT_EOK);
	
	/* 设置接收回调函数 */
	rt_device_set_rx_indicate(can1_dev, can1_rx_call);
	
	//rt_device_control(can1_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN500kBaud);
	
	//rt_device_control(can1_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_NORMAL);
    //rt_device_control(can1_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_LOOPBACK);
	
#ifdef RT_CAN_USING_HDR
    struct rt_can_filter_item items[5] =
    {
        RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 1, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x100~0x1ff，hdr 为 - 1，设置默认过滤表 */
        RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 1, 0x700, RT_NULL, RT_NULL), /* std,match ID:0x300~0x3ff，hdr 为 - 1 */
        RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 1, 0x7ff, RT_NULL, RT_NULL), /* std,match ID:0x211，hdr 为 - 1 */
        RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL),                  /* std,match ID:0x486，hdr 为 - 1 */
        {0x555, 0, 0, 1, 0x7ff, 7,}                                       /* std,match ID:0x555，hdr 为 7，指定设置 7 号过滤表 */
    };
    struct rt_can_filter_config cfg = {5, 1, items}; /* 一共有 5 个过滤表 */
    /* 设置硬件过滤表 */
    res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
    RT_ASSERT(res == RT_EOK);
#endif

	
	struct rt_can_msg rxmsg = {0};
	while(1)
	{
			/* hdr 值为 - 1，表示直接从 uselist 链表读取数据 */
			rxmsg.hdr_index = -1;
			/* 阻塞等待接收信号量 */
			rt_sem_take(&can1_rx_sem, RT_WAITING_FOREVER);
			/* 从 CAN 读取一帧数据 */
			rt_device_read(can1_dev, 0, &rxmsg, sizeof(rxmsg));
			/* 打印数据 ID 及内容 */
			if(rxmsg.rtr == RT_CAN_RTR)  //远程帧
			{
				if(rxmsg.ide == RT_CAN_EXTID)//扩展帧
				{
					rt_kprintf("ID:0x%08X RTR len:%d \n", rxmsg.id, rxmsg.len);
				}else
				{
					rt_kprintf("ID:0x%04X RTR len:%d \n", rxmsg.id, rxmsg.len);
				}
				if(rxmsg.id == 0x123)
				{
					can1_send_0x123();
				}
			}else  //数据帧
			{
				if(rxmsg.ide == RT_CAN_EXTID)//扩展帧
				{
					rt_kprintf("ID:0x%08X len:%d ", rxmsg.id, rxmsg.len);
					for (int i = 0; i < rxmsg.len; i++)
					{
							rt_kprintf(" %02X", rxmsg.data[i]);
					}
					rt_kprintf("\n");
				}else
				{
					rt_kprintf("ID:0x%04X len:%d ", rxmsg.id, rxmsg.len);
					for (int i = 0; i < rxmsg.len; i++)
					{
							rt_kprintf(" %02X", rxmsg.data[i]);
					}
					rt_kprintf("\n");
				}
				
			}
		
	}
}

int can_can1_init(void)
{
	static int can1_init = 0;
	rt_thread_t tid;
	if(can1_init > 0)
	{
		return 0;
	}
	can1_init = 1;
	
	tid = rt_thread_create("can1",can1_thread, NULL,2048,19, 10);
	if (tid != RT_NULL)
			rt_thread_startup(tid);
	return 0;
}

void can1_init(uint8_t argc, char **argv)
{
    if(argc > 0)
    {
        rt_kprintf("can1 init\n");
        can_can1_init();
    }
}
MSH_CMD_EXPORT(can1_init, can1 init);

void can1_test(uint8_t argc, char **argv)
{
	if(argc > 0)
	{
		rt_kprintf("can1 test\n");
		can1_send_0x123();
	}
}
MSH_CMD_EXPORT(can1_test, can1 test);


//void can1_debug(uint8_t argc, char **argv)
//{
//	if(argc > 1)
//	{
//		int val = atoi(argv[1]);
//		rt_kprintf("can1 debug set %d\n",val);
//	}
//}
//MSH_CMD_EXPORT(can1_debug, can1 debug);




